package com.itheima.demo5;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;


/*
    客户端

**需求**
在实际开发中，很多系统都要完成用户登录和注册功能，但需要注意的是，用户注册的登录名和密码必须是发送给服务端进行保存的，
并且注册的登录名是不能重复的，同时登录也是需要到服务端进行认证的。

**功能点具体要求**
1、开发一个客户端，具备注册，和登录功能，除非用户输入exit，否则不退出这个界面。
2、注册功能要求：可以发送登录名和密码给服务端，服务端要响应是否注册成功的结果给客户端。
  如果注册没有问题，服务端需要将用户注册的登录名和密码保存到文件中去。（注：是什么文件，可自行确定）
3、登录功能要求：用户输入登录名和密码，需要发送给服务端，服务端认证后需要把登录的结果发送给客户端接收。

本次案例中用到的属性文件在运行程序后会存储用户名和密码，源码是磊哥黑马视频的，磊哥运行后的文件里面还加了时间，
可以知道磊哥这次三小时的录播课是2023年的
D:\Idea\IntelliJIDEA2023.3.2\Code\javaseProMax\Day14JavasePro-HuangPuBan-Test\src\ users.properties
#
#Sun May 21 15:22:06 CST 2023
admin=123456
#
#Sun May 21 15:22:55 CST 2023
admin2=123
#
#Sun May 21 15:40:44 CST 2023
fdf=fasfsafs

 */
public class Client {
    //每个客户端对象，都有一个管道对象和一个扫描器对象
    private Socket socket;    //客户端一启动就要和服务端建立连接
    private Scanner sc = new Scanner(System.in);

    public static void main(String[] args) {
        try {
            // 1、创建客户端对象
            Client client = new Client();
            //启动客户端的页面
            client.start();     //try catch拦截start方法中的socket的异常
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void start() throws Exception {
        //建立连接
        socket = new Socket("127.0.0.1", 8118);     //有异常直接抛出
        System.out.println("与服务端连接成功~~~~~~~~");
        // 1、开发界面。
        // 2、提示功能
        //把这个客户端的页面放入死循环中，让他不死亡
        while (true) {
            System.out.println("请您输入操作命令：");
            System.out.println("1、注册");
            System.out.println("2、登录");
            System.out.println("请选择：");
            String command = sc.next();
            switch (command) {
                case "1":
                    // 注册
                    register();
                    break;
                case "2":
                    // 登录'
                    login();
                    break;
                case "exit":
                    System.out.println("退出系统！");
                    //退出系统的时候，把socket关掉
                    socket.close();
                    break;
            }
        }
    }

    private void register() throws Exception {
        System.out.println("==============注册==================");
        System.out.println("请您输入注册信息：");
        // 1、提示用户输入登录名和密码
        System.out.println("请输入注册用户的登录名：");
        String loginName = sc.next();

        System.out.println("请输入注册用户的登录密码");
        String passWord = sc.next();

        /*
         * TCP通信之-客户端开发
         * 客户端程序就是通过java.net包下的Socket类来实现的。
         *      构造器
         * public Socket(String host , int port)   根据指定的服务器ip、端口号请求与服务端建立连接，连接通过，就获得了客户端socket
         *      方法
         * public OutputStream getOutputStream()        获得字节输出流对象
         * public InputStream getInputStream()          获得字节输入流对象
         *
         * DataOutputStream(数据输出流)：允许把数据和其类型一并写出去。
         *
         * 我们这里是要发两个信息登录名和密码带服务店的，
         * 所以建议把 socket.getOutputStream()流封装为DataOutputStream流，
         * 因为DataOutputStream流可以写数据和数据类型
         */
        // 2、通过socket通信管道，用输出流发送登录名和密码给服务端保存给服务端
        //有异常抛出去，因为会担心服务端会把管道关闭，所以会有异常
/*      OutputStream os = socket.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        简化写法如下:
        */
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());

        // 发个1代表是注册的信号，传给服务端
        dos.writeInt(1);

        //DataOutputStream可以分段发出去，很方便
        dos.writeUTF(loginName);
        dos.writeUTF(passWord);
        //担心会在缓冲区里面导致没有及时发出去，所以刷新一下流
        dos.flush();

        // 3、马上接收服务端响应。从通信管道socket得到输入流把服务端可能的响应留下来，
        // 并且也要封装成DataInputStream，上面writeUTF，这里readUTF
        DataInputStream dis = new DataInputStream(socket.getInputStream());
        System.out.println(dis.readUTF());
    }

    private void login() throws Exception {
        System.out.println("==============登录==================");
        System.out.println("请您输入登录信息：");
        System.out.println("登录名称：");
        String loginName = sc.next();

        System.out.println("登录密码");
        String passWord = sc.next();

        // 2、发送登录名和密码给服务端保存
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());

        // 发个2代表是登录的信号，传给服务端
        dos.writeInt(2);

        dos.writeUTF(loginName);
        dos.writeUTF(passWord);
        dos.flush();

        // 3、马上接收服务端响应。
        DataInputStream dis = new DataInputStream(socket.getInputStream());
        System.out.println(dis.readUTF());
    }


}
